home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 January: Mac OS SDK / Dev.CD Jan 00 SDK2.toast / Development Kits / Hardware / PC Card SDKs / PC Card Manager 2.0 SDK / Software / PC Card Sample / ClientFramework / PCCardClient.c next >
Encoding:
C/C++ Source or Header  |  1997-06-05  |  11.2 KB  |  445 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        PCCardClient.c
  3.  
  4.     Contains:    Card-independent portion of the PC Card Sample Client
  5.  
  6.     Written by:    Dave Falkenburg with lots of helpful code from:
  7.                     Phillip Nguyen, Greg Brewer, timothy warden,
  8.                     James Blair, Mark D. Rustad, and Richard W. Mincher.
  9.  
  10.     Copyright © 1995 by Apple Computer, Inc., all rights reserved.
  11.  
  12.     Change History (most recent first):
  13.  
  14.          <0>     11/28/95    DRF        first code.
  15. */
  16.  
  17. #include "PCCardClient.h"
  18.  
  19. #include <Resources.h>
  20. #include <ToolUtils.h>
  21. #include <Gestalt.h>
  22.  
  23.  
  24. //    internal utility functions
  25.  
  26. static    void            CopyPStringToBoundedCString(StringPtr sourcePString,char * destCString,UInt16 *size);
  27. static    void            SetClientEventMaskForSocket(PCCardClientGlobalsRec * globals, UInt16 socket, UInt16 eventMask);
  28. static    pascal    OSErr    DetachIcons(ResType resType, Handle *hdl, void * param);
  29.  
  30.  
  31.  
  32. #if    GENERATINGPOWERPC
  33. unsigned long    __procinfo = kPascalStackBased;
  34. #endif
  35.  
  36. void
  37. main()
  38.     {
  39.     Handle    me = GetResource('INIT',128);
  40.     UInt32    numberOfSockets = 0;
  41.     Boolean    weInstalled = false;
  42.         
  43.     IfDebugStr("\pPCCardClient");
  44.     
  45.     //    only run if the PC Card manager is available
  46.     
  47.     if (PCCardManagerIsAvailable(&numberOfSockets) && (numberOfSockets != 0))
  48.         {
  49.         THz        savedZone = GetZone();
  50.  
  51.         SetZone(SystemZone());
  52.         weInstalled = (InstallPCCardClient(numberOfSockets) == noErr);
  53.         SetZone(savedZone);
  54.         }
  55.         
  56.     if (weInstalled)
  57.         {
  58.         DetachResource(me);        //    make sure we don’t disappear if we loaded!
  59. //        ShowINIT(kExtensionIconID);
  60.         }
  61. //    else
  62. //        ShowINIT(kExtensionNotLoadedIconID);
  63.     }
  64.  
  65.  
  66. Boolean
  67. PCCardManagerIsAvailable(UInt32 * numberOfSockets)
  68.     {
  69.     long    featureFlags;
  70.     OSErr    err;
  71.  
  72.     err = Gestalt(gestaltCardServicesAttr,&featureFlags);
  73.     if (err == noErr)
  74.         {
  75.         if (featureFlags & (1 << gestaltCardServicesPresent))
  76.             {
  77.             GetCardServicesInfoPB    csInfoPB;
  78.             Str255                    vendorString;
  79.             
  80.             csInfoPB.reserved        = 0;
  81.             csInfoPB.vStrLen        = sizeof(vendorString)-1;
  82.             csInfoPB.vendorString    = &vendorString[1];
  83.     
  84.             if ( CSGetCardServicesInfo(&csInfoPB) == noErr ) 
  85.                 {
  86.                 *numberOfSockets = csInfoPB.count;
  87.                 return true;
  88.                 }
  89.             }
  90.         }
  91.     
  92.     return false;
  93.     }
  94.  
  95.  
  96. OSErr
  97. InstallPCCardClient(UInt32 numberOfSockets)
  98.     {
  99.     OSErr                        err;
  100.     RegisterClientPB            registerClientPB;
  101.     VendorSpecificPB            vendorSpecificPB;
  102.     PCCardClientGlobalsRec *    globals;
  103.  
  104.     //    Allocate our globals, note that we allocate additional per-socket
  105.     //    state so that our client can track multiple cards
  106.     
  107.     globals = (PCCardClientGlobalsRec *) NewPtrSysClear(sizeof(PCCardClientGlobalsRec)
  108.                                                     + (numberOfSockets * sizeof(PCCardPerSocketState)));
  109.     if (globals == NULL)
  110.         return MemError();    
  111.  
  112.     globals->numberOfSockets = numberOfSockets;
  113.  
  114.     //    fetch description strings & icons (vendor information for this client) 
  115.     //  from our resource fork
  116.     
  117.     GetIndString(globals->cardName, kCardStringList, kCardName);
  118.     GetIndString(globals->cardType, kCardStringList, kCardType);
  119.     GetIndString(globals->vendorName, kCardStringList, kCardVendorName);
  120.     GetIndString(globals->clientName, kCardStringList, kCardClientName);
  121.  
  122.     if (GetIconSuite(&globals->cardIconSuite, kCardIconID, svAllAvailableData) != noErr)
  123.         globals->cardIconSuite = NULL;
  124.  
  125.     if (globals->cardIconSuite)        //    If there are icons, detach them
  126.         ForEachIconDo(globals->cardIconSuite, svAllAvailableData, NewIconActionProc(DetachIcons), 0);
  127.  
  128.  
  129.     //    register our client
  130.     
  131.     registerClientPB.clientEntry = NewPCCardCSClientProc(HandlePCCardEvent);
  132.     registerClientPB.attributes = kPCCardClientAttributes;
  133.     registerClientPB.eventMask = kInterestingPCCardEvents;
  134.     registerClientPB.clientData = (void *) globals;
  135.     registerClientPB.version = 0x210;
  136.     
  137.     err = CSRegisterClient(®isterClientPB);
  138.     if (err != noErr)
  139.         return err;
  140.  
  141.     globals->clientHandle = registerClientPB.clientHandle;
  142.  
  143.  
  144.     //    enable socket events for our client
  145.     
  146.     vendorSpecificPB.clientHandle        = globals->clientHandle;
  147.     vendorSpecificPB.vsCode                = vsEnableSocketEvents;
  148.     vendorSpecificPB.socket                = 0;
  149.     vendorSpecificPB.dataLen            = 0;
  150.     vendorSpecificPB.vsDataPtr            = nil;
  151.     
  152.     err = CSVendorSpecific(&vendorSpecificPB);
  153.     if (err != noErr)
  154.         (void) CSDeregisterClient(®isterClientPB);
  155.         
  156.     return err;
  157.     }
  158.  
  159.  
  160.  
  161. pascal
  162. OSErr    HandlePCCardEvent(ClientCallbackPBPtr pb)
  163.     {
  164.     PCCardClientGlobalsRec *     globals = (PCCardClientGlobalsRec *) pb->clientData;
  165.     PCCardPerSocketState *        socketState = &(globals->socketState[pb->socket]);
  166.     OSErr                        result = noErr;
  167.     
  168.     switch (pb->message)
  169.         {
  170.         case    kCSFunctionInterruptMessage:    //    FUNCTION_INTERRUPT
  171.             if (socketState->cardFlags & kCardIsConfigured)
  172.                 MyCardInterruptHandler(globals,socketState,pb->socket);
  173.             break;
  174.             
  175.         case    kCSCardRemovalMessage:            //    CARD_REMOVAL
  176.             result = HandleCardRemoval(globals,socketState,pb);
  177.             break;
  178.  
  179.         case    kCSEjectionRequestMessage:        //    EJECTION_REQUEST
  180.             result = HandleCardEjectRequest(globals,socketState,pb);
  181.             break;
  182.  
  183.         case    kCSCardReadyMessage:            //    CARD_READY
  184.             // If it is configured we don't have to do anything
  185.             if (socketState->cardFlags & kCardIsConfigured)
  186.                 break;
  187.  
  188.             result = HandleCardReady(globals,socketState,pb);
  189.             break;
  190.         
  191.         case    kCSClientInfoMessage:            //    CLIENT_INFO
  192.             result = HandleGetClientInfo(globals,(GetClientInfoPB *) pb->buffer);
  193.             break;
  194.         
  195.         case    kCSPMResumeMessage:                //    PM_RESUME
  196.             result = HandleCardResume(globals,pb);
  197.             break;
  198.  
  199.         case    kCSPMSuspendMessage:            //    PM_SUSPEND
  200.             if (socketState->cardFlags & kCardIsConfigured)
  201.                 result = HandleCardSuspend(globals,pb);
  202.             break;
  203.                     
  204.         default:
  205.             break;
  206.         }
  207.  
  208.     return result;
  209.     }
  210.  
  211.     
  212. OSErr    HandleCardReady(PCCardClientGlobalsRec * globals,PCCardPerSocketState * socketState, ClientCallbackPBPtr pb)
  213.     {
  214.     IfDebugStr("\pCARD READY");
  215.  
  216.     if (IsThisMyCard(globals,pb->socket))
  217.         if (ConfigureMyCard(globals,socketState,pb->socket) == noErr)
  218.             {
  219.             socketState->cardFlags |= kCardIsConfigured;
  220.             return noErr;
  221.             }
  222.             
  223.     //    Once we have detected that a card is not for us (after CARD_READY is received
  224.     //    for a card wedon’t recognize) we mask out all events for that socket, except
  225.     //    for card removal.  Once we get a card removal, we will ask for all our interesting
  226.     //    events.
  227.     
  228.     SetClientEventMaskForSocket(globals,pb->socket,kCSCardDetectChangeEvent);
  229.  
  230.     return kCSUnsupportedFunctionErr;
  231.     }
  232.  
  233.  
  234. OSErr    HandleCardRemoval(PCCardClientGlobalsRec * globals,PCCardPerSocketState * socketState, ClientCallbackPBPtr pb)
  235.     {
  236.     IfDebugStr("\pCARD REMOVAL");
  237.  
  238.     if (socketState->cardFlags & kCardIsConfigured)
  239.         {
  240.         //    If we haven’t released our configuration, go ahead an do that
  241.  
  242.         (void) UnconfigureMyCard(globals,socketState,pb->socket);
  243.         }
  244.  
  245.         
  246.     //    Make sure our slate is clean
  247.  
  248.     socketState->cardFlags = 0;
  249.  
  250.     //    Once we have detected that a card has been removed (via CARD_REMOVAL)
  251.     //    we reset the event mask so that we can catch all pertinent events for
  252.     //    the next card
  253.  
  254.     SetClientEventMaskForSocket(globals,pb->socket, kInterestingPCCardEvents);
  255.  
  256.     return noErr;
  257.     }
  258.  
  259.     
  260. OSErr    HandleCardEjectRequest(PCCardClientGlobalsRec * globals,PCCardPerSocketState * socketState, ClientCallbackPBPtr pb)
  261.     {
  262.     if (socketState->cardFlags & kCardIsConfigured)
  263.         {
  264.         IfDebugStr("\pEJECT REQUEST");
  265.         
  266.         (void) UnconfigureMyCard(globals,socketState,pb->socket);
  267.         socketState->cardFlags = 0;
  268.  
  269.         return noErr;
  270.         }
  271.     
  272.     return noErr;
  273.     }
  274.  
  275.     
  276. OSErr    HandleGetClientInfo(PCCardClientGlobalsRec * globals, GetClientInfoPB * pb)
  277.     {
  278.     OSErr                    result = kCSUnsupportedFunctionErr;
  279.     PCCardPerSocketState *    socketState;
  280.     UInt16                    subFunction = (pb->u.clientInfo.attributes & kCSInfoSubfunctionMask);
  281.  
  282.     if (subFunction == kCSClientInfoSubfunction)
  283.         {
  284.         IfDebugStr("\pNormal GETCLIENTINFO");
  285.  
  286.         pb->u.clientInfo.revision = kMyClientVersion;        /* <-  BCD value of client's revision*/
  287.         pb->u.clientInfo.csLevel = kRequiredCSLevel;        /* <-  BCD value of CS release*/
  288.         pb->u.clientInfo.revDate = kMyClientRevisionDate;    /* <-  revision date: y[15-9], m[8-5], d[4-0]*/
  289.  
  290.         //    provide our name string, if they want it
  291.  
  292.         CopyPStringToBoundedCString(globals->clientName,
  293.                                     (char *) pb->u.clientInfo.nameString,
  294.                                     (UInt16 *) &pb->u.clientInfo.nameLen);
  295.  
  296.         //    ...and/or our vendor string
  297.  
  298.         CopyPStringToBoundedCString(globals->vendorName,
  299.                                     (char *) pb->u.clientInfo.vendorString,
  300.                                     (UInt16 *) &pb->u.clientInfo.vStringLen);
  301.  
  302.         return noErr;
  303.         }
  304.  
  305.     socketState = &(globals->socketState[pb->u.alternateTextString.socket]);
  306.  
  307.     if (socketState->cardFlags & kCardIsConfigured)
  308.         {
  309.         switch (subFunction)
  310.             {
  311.             case    kCSCardNameSubfunction:
  312.                 IfDebugStr("\pkCSCardNameSubfunction");
  313.                 if (globals->cardName[0])        //    If we have a custom card name, return it.
  314.                     {
  315.                     CopyPStringToBoundedCString(globals->cardName,
  316.                                                 (char *) pb->u.alternateTextString.text,
  317.                                                 (UInt16 *) &pb->u.alternateTextString.length);
  318.                     result = noErr;
  319.                     }
  320.                 break;
  321.                 
  322.             case    kCSCardTypeSubfunction:
  323.                 IfDebugStr("\pkCSCardTypeSubfunction");
  324.                 if (globals->cardType[0])        //    If we have a custom card type, return it.
  325.                     {
  326.                     CopyPStringToBoundedCString(globals->cardType,
  327.                                                 (char *) pb->u.alternateTextString.text,
  328.                                                 (UInt16 *) &pb->u.alternateTextString.length);
  329.                     result = noErr;
  330.                     }
  331.                 break;
  332.                 
  333.             case    kCSHelpStringSubfunction:
  334.                 IfDebugStr("\pkCSHelpStringSubfunction");
  335.                 if (globals->helpString[0])        //    If we have a help balloon string, return it.
  336.                     {
  337.                     CopyPStringToBoundedCString(globals->helpString,
  338.                                                 (char *) pb->u.alternateTextString.text,
  339.                                                 (UInt16 *) &pb->u.alternateTextString.length);
  340.                     result = noErr;
  341.                     }
  342.                 break;
  343.                 
  344.             case    kCSCardIconSubfunction:
  345.                 IfDebugStr("\pkCSCardIconSubfunction");
  346.                 if (globals->cardIconSuite)        //    If we have a custom icon, return it.
  347.                     {
  348.                     pb->u.alternateIcon.iconSuite = globals->cardIconSuite;
  349.                     result = noErr;
  350.                     }
  351.                 break;
  352.                 
  353.             case    kCSActionProcSubfunction:
  354.                 IfDebugStr("\pkCSActionProcSubfunction");
  355.                 break;
  356.                 
  357.             default:
  358.                 IfDebugStr("\pUnknown GetClientInfo variant");
  359.                 break;
  360.             }
  361.         }
  362.  
  363.     return result;
  364.     }
  365.  
  366.  
  367. OSErr    HandleCardSuspend(PCCardClientGlobalsRec * /* globals */,ClientCallbackPBPtr /* pb */)
  368.     {
  369. //    IfDebugStr("\pPM SUSPEND");
  370.     
  371.     return noErr;
  372.     }
  373.  
  374.  
  375. OSErr    HandleCardResume(PCCardClientGlobalsRec * /* globals */,ClientCallbackPBPtr /* pb */)
  376.     {
  377. //    IfDebugStr("\pPM RESUME");
  378.  
  379.     return noErr;
  380.     }
  381.  
  382.  
  383.  
  384.  
  385. //    SetClientEventMaskForSocket
  386. //
  387. //        a wrapper function for CSSetClientEventMask to make the code more readable
  388.  
  389. void
  390. SetClientEventMaskForSocket(PCCardClientGlobalsRec * globals, UInt16 socket, UInt16 eventMask) 
  391.     {
  392.     GetSetClientEventMaskPB        eventMaskPB;
  393.     
  394.     eventMaskPB.clientHandle = globals->clientHandle;
  395.     eventMaskPB.socket = socket;
  396.     eventMaskPB.attributes = kCSEventMaskThisSocketOnly;
  397.     eventMaskPB.eventMask = eventMask;
  398.     
  399.     CSSetClientEventMask(&eventMaskPB);
  400.     }
  401.  
  402.  
  403. //    CopyPStringToBoundedCString
  404. //
  405. //        a utility function called by HandleGetClientInfo which is used to copy
  406. //        strings into a clients buffer.
  407.  
  408. void
  409. CopyPStringToBoundedCString(StringPtr sourcePString,char * destCString,UInt16 *size)
  410.     {
  411.     UInt32    strLen = *size;
  412.     
  413.     if ( strLen != 0 )
  414.         {
  415.         if (sourcePString[0] < strLen)
  416.             strLen = sourcePString[0] + 1;
  417.             
  418.         BlockMoveData(&sourcePString[1], destCString, strLen-1);
  419.         destCString[strLen-1] = 0;
  420.         *size = strLen;
  421.         }
  422.     }
  423.  
  424.  
  425. //    DetachIcons
  426. //
  427. //        an IconActionProc which detaches an icon family from the extension file,
  428. //        and keeps it around.
  429.  
  430. pascal OSErr
  431. DetachIcons(ResType resType, Handle *hdl, void * /* p */)
  432.     {
  433.     if (hdl)
  434.         {
  435.         if (resType)
  436.             {
  437.             LoadResource(*hdl);
  438.             HNoPurge(*hdl);
  439.             DetachResource(*hdl);
  440.             }
  441.         }
  442.  
  443.     return noErr;
  444.     }
  445.